package cn.com.doone.common.uc.web.controller;

import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import cn.com.doone.common.uc.domain.oauth.ClientDetails;
import cn.com.doone.common.uc.service.OauthService;
import cn.com.doone.common.uc.service.dto.LoginDto;
import cn.com.doone.common.uc.utils.DES3;
import cn.com.doone.common.uc.utils.PasswordUtils;
import cn.com.doone.common.uc.utils.PropertiesUtils;
import cn.com.doone.common.uc.utils.RedisUtils;
import cn.com.doone.common.uc.utils.StringUtils;

/**
 * 15-6-10
 * <p/>
 * Just test Shiro
 *
 * @author Shengzhao Li
 */
@Controller
public class ShiroController {

	private static final Logger LOG = LoggerFactory.getLogger(ShiroController.class);
	@Autowired
	private PropertiesUtils propertiesUtils;

	@Autowired
	private OauthService oauthService;

	@RequestMapping("index")
	public String index() {
		return "index";
	}

	@RequestMapping("unauthorized")
	public String unauthorized() {
		return "unauthorized";
	}

	/*
	 * Logout
	 */
	@RequestMapping("logout")
	public String logout() {
		final Subject subject = SecurityUtils.getSubject();
		LOG.debug("{} is logout", subject.getPrincipal());
		subject.logout();
		return "oauth_login";
	}

	/**
	 * 退出
	 * 
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	@RequestMapping("accountLogout")
	public void accountLogout(HttpServletRequest request, HttpServletResponse response) throws Exception {
		final Subject subject = SecurityUtils.getSubject();
		LOG.debug("{} is logout", subject.getPrincipal());
		subject.logout();

		String redirectUrl = request.getParameter("redirect_url");

		if ("".equals(redirectUrl) || redirectUrl == null) {
			String clientId = request.getParameter("client_id");
			String username = request.getParameter("username");
			if(StringUtils.isNotNull(clientId) && StringUtils.isNotNull(username)) {
				//清除token
				oauthService.removeAuthCode(clientId, username);
			}
			ClientDetails clientDetails = oauthService.loadClientDetails(clientId);
			response.sendRedirect(clientDetails.getClientUri());
		} else {
			response.sendRedirect(redirectUrl);
		}

	}
	
	/*
	 * Go login page
	 */
	@RequestMapping(value = "login", method = RequestMethod.GET)
	public String login(Model model) {
		final LoginDto loginDto = new LoginDto();
		// TODO: Just testing
		loginDto.setUsername("test");

		model.addAttribute("formDto", loginDto);
		return "login";
	}

	@RequestMapping(value = "login", method = RequestMethod.POST)
	public String login(@ModelAttribute("formDto") LoginDto formDto, BindingResult errors) {

		UsernamePasswordToken token = formDto.token();
		token.setRememberMe(false);

		try {
			SecurityUtils.getSubject().login(token);
		} catch (Exception e) {
			LOG.debug("Error authenticating.", e);
			errors.rejectValue("username", null, "The username or password was not correct.");
			return "login";
		}

		return "redirect:index";
	}

	@RequestMapping(value = "changePassword", method = RequestMethod.POST)
	@ResponseBody
	public Map<String, Object> changePassword(HttpServletRequest request, HttpServletResponse response) {

		List<String> messageList = new ArrayList<String>();
		Map<String, Object> resultMap = new HashMap<String, Object>();

		String userAccount = (String) request.getParameter("userAccount");
		String oldPassword = (String) request.getParameter("oldPassword");
		String newPassword = (String) request.getParameter("newPassword");

		// 验证IP是否锁定
		RedisUtils.validIp(request, resultMap);
		if (!resultMap.isEmpty()) {
			return resultMap;
		}

		// 验证账号是否锁定
		Map<String, Object> accountResultMap = new HashMap<String, Object>();
		accountResultMap.put("userAccount", userAccount);

		oauthService.validAccountLock(accountResultMap);

		if (accountResultMap.get("error") != null && (Boolean) accountResultMap.get("error")) {
			messageList.add((String) accountResultMap.get("errorMessage"));
			resultMap.put("success", false);
			resultMap.put("message", messageList);
			return resultMap;
		}

		boolean isCorrect = false;
		try {
			isCorrect = oauthService.validCorrectPassword(userAccount, oldPassword, request);
		} catch (NoSuchAlgorithmException e1) {
			e1.printStackTrace();
		}

		if (!isCorrect) {
			// redis添加IP记录
			RedisUtils.addIpList(request);

			resultMap.put("success", false);
			resultMap.put("message", "旧密码不正确");
			return resultMap;
		}
		String isWeak = PasswordUtils.checkPassword(newPassword);

		if (StringUtils.isNotNull(isWeak)) {
			resultMap.put("success", false);
			resultMap.put("message", isWeak);
			return resultMap;
		}

		try {

			oauthService.changePassword(userAccount, PasswordUtils.openLdapMD5((newPassword)),
					DES3.encode(newPassword, propertiesUtils.getSecretKey()));

			Calendar cal = Calendar.getInstance();
			int year = cal.get(Calendar.YEAR);
			newPassword = DES3.encode(newPassword, "ZGJMWQJSTMDZQQRDOONE" + String.valueOf(year));
			UsernamePasswordToken token = new UsernamePasswordToken(userAccount, newPassword);
			SecurityUtils.getSubject().login(token);

			LOG.debug("用户" + userAccount + "密码修改成功");
		} catch (Exception e) {
			e.printStackTrace();
			resultMap.put("success", false);
			messageList.add("密码修改失败！！");

			LOG.error("用户" + userAccount + "失败, 失败原因：" + messageList);
		}

		resultMap.put("success", true);
		resultMap.put("message", "修改成功");
		return resultMap;
	}

	@RequestMapping(value = "findWedoStaffIdByAccount", method = RequestMethod.POST)
	@ResponseBody
	public Map<String, Object> findWedoStaffIdByAccount(HttpServletRequest request, HttpServletResponse response) {
		Map<String, Object> resultMap = new HashMap<String, Object>();

		try {

			String appCode = (String) request.getParameter("appCode");
			String userAccount = (String) request.getParameter("userAccount");

			Map<String, Object> userInfoMap = oauthService.findWedoStaffIdByAccount(appCode, userAccount);

			resultMap.put("success", true);
			resultMap.put("message", "获取用户信息成功！！");
			resultMap.put("wedoUserIds", userInfoMap.get("wedoUserIds"));

			LOG.debug("用户" + userAccount + "获取WEDO ID");

		} catch (Exception e) {
			e.printStackTrace();

			resultMap.put("success", false);
			resultMap.put("message", "获取用户信息失败");
		}

		return resultMap;
	}

	private int isSimplePwd(String password) {

		if (password.length() < 6) {
			return 0;
		}

		int ls = 0;

		Pattern pattern = Pattern.compile("([a-z])+");
		Matcher matcher = pattern.matcher(password);
		if (matcher.find()) {
			ls++;
		}

		pattern = Pattern.compile("([0-9])+");
		matcher = pattern.matcher(password);
		if (matcher.find()) {
			ls++;
		}

		pattern = Pattern.compile("([A-Z])+");
		matcher = pattern.matcher(password);
		if (matcher.find()) {
			ls++;
		}

		pattern = Pattern.compile("[^a-zA-Z0-9]+");
		matcher = pattern.matcher(password);
		if (matcher.find()) {
			ls++;
		}

		return ls;
	}

}
